﻿
using CPF.Input;
using CPFUI.IControl;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace CPFUI.IHelper
{
    public class MouseHook
    {
        private Point point;
        private Point Point
        {
            get { return point; }
            set
            {
                if (point != value)
                {
                    point = value;
                    if (MouseMoveEvent != null)
                    {
                        var e = new MouseButtonEventArgs(null,true,false,false, new CPF.Drawing.Point(point.X, point.Y),null,MouseButton.Left);
                        MouseMoveEvent(this, e);
                    }
                }
            }
        }
        private int hHook;
        private static int hMouseHook = 0;
        private const int WM_MOUSEMOVE = 0x200;
        private const int WM_LBUTTONDOWN = 0x201;
        private const int WM_RBUTTONDOWN = 0x204;
        private const int WM_MBUTTONDOWN = 0x207;
        private const int WM_LBUTTONUP = 0x202;
        private const int WM_RBUTTONUP = 0x205;
        private const int WM_MBUTTONUP = 0x208;
        private const int WM_LBUTTONDBLCLK = 0x203;
        private const int WM_RBUTTONDBLCLK = 0x206;
        private const int WM_MBUTTONDBLCLK = 0x209;

        public const int WH_MOUSE_LL = 14;
        public Win32Helper.HookProc hProc;
        public MouseHook()
        {
            this.Point = new Point();
        }
        public int SetHook()
        {
            hProc = new Win32Helper.HookProc(MouseHookProc);
            hHook = Win32Helper.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
            return hHook;
        }
        public void UnHook()
        {
            Win32Helper.UnhookWindowsHookEx(hHook);
        }
        private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            Win32Helper.MouseHookStruct MyMouseHookStruct = (Win32Helper.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Helper.MouseHookStruct));
            if (nCode < 0)
            {
                return Win32Helper.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
            else
            {
                MouseButton button = MouseButton.None;
                int clickCount = 0;
                switch ((Int32)wParam)
                {
                    case WM_LBUTTONDOWN:
                        button = MouseButton.Left;
                        clickCount = 1;;
                        MouseDownEvent(this, new MouseButtonEventArgs(null, true, false, false, new CPF.Drawing.Point(point.X, point.Y), null, button));
                        break;
                    case WM_RBUTTONDOWN:
                        button = MouseButton.Right;
                        clickCount = 1;
                        MouseDownEvent(this, new MouseButtonEventArgs(null, false, true, false, new CPF.Drawing.Point(point.X, point.Y), null, button));
                        break;
                    case WM_MBUTTONDOWN:
                        button = MouseButton.Middle;
                        clickCount = 1;
                        MouseDownEvent(this, new MouseButtonEventArgs(null, false, false, true,new CPF.Drawing.Point(point.X, point.Y), null, button));
                        break;
                    case WM_LBUTTONUP:
                        button = MouseButton.Left;
                        clickCount = 1;
                        MouseUpEvent(this, new MouseButtonEventArgs(null, true, false, false, new CPF.Drawing.Point(point.X, point.Y), null, button));
                        break;
                    case WM_RBUTTONUP:
                        button = MouseButton.Right;
                        clickCount = 1;
                        MouseUpEvent(this, new MouseButtonEventArgs(null, false, true, false, new CPF.Drawing.Point(point.X, point.Y), null, button));
                        break;
                    case WM_MBUTTONUP:
                        button = MouseButton.Middle;
                        clickCount = 1;
                        MouseUpEvent(this, new MouseButtonEventArgs(null, false, false, true, new CPF.Drawing.Point(point.X, point.Y), null, button));
                        break;
                }

                this.Point = new Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
                return Win32Helper.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
        }

        public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
        public event MouseMoveHandler MouseMoveEvent;

        public delegate void MouseClickHandler(object sender, MouseEventArgs e);
        public event MouseClickHandler MouseClickEvent;

        public delegate void MouseDownHandler(object sender, MouseEventArgs e);
        public event MouseDownHandler MouseDownEvent;

        public delegate void MouseUpHandler(object sender, MouseEventArgs e);
        public event MouseUpHandler MouseUpEvent;
    }

    public class KeyHook {
        [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
        public static extern void keybd_event(IControl.Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
    }
}
